//
// Created by Administrator on 2021/9/26.
//

#include "Vector3.h"

#include <cmath>

Vector3::Vector3() {
    Vector3(0.0f, 0.0f, 0.0f);
}

Vector3::~Vector3() {
    //delete _value_ptr;
}

Vector3::Vector3(float v[3]) {
    if(nullptr == v){
        return;
    }
    x = v[0]; y = v[1]; z = v[2];
    _value_ptr = new float[3]{x, y, z};
}

Vector3::Vector3(float nx, float ny, float nz) {
    x = nx; y = ny; z = nz;
    _value_ptr = new float[3]{x, y, z};
}

Vector3::Vector3(const Vector3 &v) {
    x = v.x; y = v.y; z = v.z;
    _value_ptr = new float[3]{x, y, z};
}

Vector3 &Vector3::operator=(const Vector3 &v) {
    x = v.x;
    y = v.y;
    z = v.z;
    return *this;
}

bool Vector3::operator==(const Vector3 &v) const{
    return x == v.x && y == v.y && z == v.z;
}

bool Vector3::operator!=(const Vector3 &v) const{
    return x != v.x || y != v.y || z != v.z;
}

Vector3 Vector3::operator+(const Vector3 &v) {
    return Vector3(x + v.x, y + v.y, z + v.z);
}

Vector3 Vector3::operator-(const Vector3 &v) {
    return Vector3(x - v.x, y - v.y, z - v.z);
}

Vector3 Vector3::operator*(float a) {
    x *= a; y *= a; z *= a;
    return Vector3(x * a, y * a, z * a);
}

Vector3 Vector3::operator/(float a) {
    float _a = 1 / a;
    return Vector3(x * _a, y * _a, z * _a);
}

float Vector3::length() {
    return std::sqrt(x * x + y * y + z * z);
}

void Vector3::normalize() {
    float len = length();
    x = x / len;
    y = y / len;
    z = z / len;
}

Vector3 Vector3::zero() {
    return Vector3(0.0f, 0.0f, 0.0f);
}

Vector3 Vector3::identity() {
    return Vector3(1.0f, 1.0f, 1.0f);
}

float Vector3::operator*(const Vector3 &v) const{
    return x * v.x + y * v.y + z * v.z;
}

float *Vector3::value_ptr() {
    _value_ptr[0] = x;
    _value_ptr[1] = y;
    _value_ptr[2] = z;
    return _value_ptr;
}

String Vector3::toString() {
    String str = "(x = " + std::to_string(x) + ", y = " + std::to_string(y) + ", z = " + std::to_string(z) + ")";
    return str;
}

/**
* 向量相减
*/
Vector3 Vector3::subtractVectors(const Vector3& v1, const Vector3& v2) {
    float _x = v1.x - v2.x;
    float _y = v1.y - v2.y;
    float _z = v1.z - v2.z;
    return Vector3(_x, _y, _z);
}

/**
 * 计算两个向量的夹角 ||a||||b||cosθ = a·b
 * @param v1 向量1
 * @param v2 向量2
 * @return 角度
 */
float Vector3::angle(Vector3 v1, Vector3 v2, AngleType angleType) {
    float mlen = v1.length() * v2.length();
    float rad = std::acos(v1 * v2 * (1 / mlen));
    if(AngleType::DEGREE == angleType){
        return Angle::rad2deg(rad);
    }
    return rad;
}

/**
 * 标量左乘
 * @param f 标量
 * @param v2 向量
 * @return 结果
 */
Vector3 Vector3::multiply(float f, Vector3 v2) {
    return Vector3(v2.x * f, v2.y * f, v2.z * f);
}

/**
 * 点乘
 * @param v1 向量1
 * @param v2 向量2
 * @return 点乘结果
 */
float Vector3::multiply(Vector3 v1, Vector3 v2) {
    return v1 * v2;
}

/**
 * 叉乘
 * @param v1 向量1
 * @param v2 向量2
 * @return 叉乘结果
 */
Vector3 Vector3::crossProduct(const Vector3& v1, const Vector3& v2) {
    return Vector3(
            v1.y * v2.z - v1.z * v2.y,
            v1.z * v2.x - v1.x * v2.z,
            v1.x * v2.y - v1.y * v2.x
            );
}

/**
 * 两点间距离
 * @param v1 向量1
 * @param v2 向量2
 * @return 距离
 */
float Vector3::distance(Vector3 v1, Vector3 v2) {
    float dx = v1.x - v2.x;
    float dy = v1.y - v2.y;
    float dz = v1.z - v2.z;
    return std::sqrt(dx * dx + dy * dy + dz * dz);
}




